package com.keliangliu.demo.lock;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;

/**
 * 这个内部是运用AQS 来实现自定义锁
 * AQS 里面对应的是state 是 AtomicInteger 自旋锁，如果当前线程持有的state是1的话，就会进入一个CLH队列等待
 *
 */
public class MAQSLock implements Lock {

    private Sync sync = new Sync();
    @Override
    public void lock() {
        sync.acquire(1);
    }

    @Override
    public void lockInterruptibly() throws InterruptedException {

    }

    @Override
    public boolean tryLock() {
        return false;
    }

    @Override
    public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
        return false;
    }

    @Override
    public void unlock() {
        sync.release(1);
    }

    @Override
    public Condition newCondition() {
        return null;
    }


    private class Sync extends AbstractQueuedSynchronizer {

        /**
         * 尝试去拿锁
         * @param arg
         * @return
         */
        @Override
        protected boolean tryAcquire(int arg) {
            assert arg == 1;
            //去比较state的值是否是0，如果是0就去把他设置成1，并且让当前线程成为锁线程
            if(compareAndSetState(0,1)) {
                //让当前的线程去持有锁
                setExclusiveOwnerThread(Thread.currentThread());
                return true;
            }

            return false;
        }

        /**
         * 尝试去释放锁
         * @param arg
         * @return
         */
        @Override
        protected boolean tryRelease(int arg) {
            assert  arg == 1;
            //
            if(!isHeldExclusively()) {
                throw new IllegalMonitorStateException();
            }
            setExclusiveOwnerThread(null);
            setState(0);
            return true;
        }


        /**
         * 判断当前线程锁线程
         * @return
         */
        @Override
        protected boolean isHeldExclusively() {
            return Thread.currentThread() == getExclusiveOwnerThread();
        }
    }
}
